#include <config.h>
#include <text_reader.h>
#include <encoding_manager.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fonts_manager.h>
#include <render.h>

/* 前向声明 */
__attribute__((unused))
static void ConvertUnsupportedChars(char *pucText);

/* 文本阅读器全局配置 */
static struct {
    int iInited;             /* 是否已初始化 */
    int iDefaultFontSize;    /* 默认字体大小 */
    unsigned int dwFgColor;  /* 前景色 */
    unsigned int dwBgColor;  /* 背景色 */
    int iLinesPerScreen;     /* 每屏显示的行数 */
    int iCharsPerLine;       /* 每行显示的字符数 */
} g_tTextReaderCfg = {
    .iInited = 0,
    .iDefaultFontSize = 16,
    .dwFgColor = 0x000000,   /* 黑色文字 */
    .dwBgColor = 0xFFFFFF,   /* 白色背景 */
    .iLinesPerScreen = 20,   /* 默认值，会在初始化时根据屏幕尺寸计算 */
    .iCharsPerLine = 50      /* 默认值，会在初始化时根据屏幕尺寸计算 */
};

/* 添加页面描述数据结构，用于记录页面数据 */
typedef struct PageDesc {
    int iPage;  /* 页码 */
    int iStartPos;  /* 页面在文件中的起始位置 */
    int iEndPos;    /* 页面在文件中的结束位置 */
    struct PageDesc *ptPrePage;   /* 上一页指针 */
    struct PageDesc *ptNextPage;  /* 下一页指针 */
} T_PageDesc, *PT_PageDesc;

/* 页面链表 */
static PT_PageDesc g_ptPages = NULL;    /* 所有页面链表的头 */
static PT_PageDesc g_ptCurPage = NULL;  /* 当前页面 */

/**********************************************************************
 * 函数名称： RecordPage
 * 功能描述： 记录页面信息，将新页面添加到链表中
 * 输入参数： ptPageNew - 新的页面描述
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void RecordPage(PT_PageDesc ptPageNew)
{
    PT_PageDesc ptPage;
        
    if (!g_ptPages)
    {
        /* 第一个页面 */
        g_ptPages = ptPageNew;
    }
    else
    {
        /* 找到链表尾部 */
        ptPage = g_ptPages;
        while (ptPage->ptNextPage)
        {
            ptPage = ptPage->ptNextPage;
        }
        
        /* 加入链表 */
        ptPage->ptNextPage   = ptPageNew;
        ptPageNew->ptPrePage = ptPage;
    }
}

/**********************************************************************
 * 函数名称： IsTxtFile
 * 功能描述： 判断文件是否为文本文件
 * 输入参数： ptFileMap - 文件映射结构体指针
 * 输出参数： 无
 * 返 回 值： 1 - 是文本文件, 0 - 不是文本文件
 ***********************************************************************/
int IsTxtFile(PT_FileMap ptFileMap)
{
    /* 增强的文本文件检测逻辑 */
    unsigned char *pucBufHead;
    int fileSize;
    char *ext;
    int i;
    int binCount = 0;
    int textCount = 0;
    int nullCount = 0;
    
    /* 检查输入参数 */
    if (!ptFileMap || !ptFileMap->pucFileMapMem || ptFileMap->iFileSize <= 0)
    {
        DBG_PRINTF("ERROR: Invalid file map parameters\n");
        return 0;
    }
    
    /* 详细的文件信息输出 */
    DBG_PRINTF("DEBUG: Checking file: %s, size: %d bytes\n", 
               ptFileMap->strFileName, ptFileMap->iFileSize);
    
    pucBufHead = ptFileMap->pucFileMapMem;
    fileSize = ptFileMap->iFileSize;
    
    /* 打印文件前32字节，帮助分析 */
    DBG_PRINTF("DEBUG: File header (hex): ");
    for (i = 0; i < 32 && i < fileSize; i++) {
        DBG_PRINTF("%02x ", pucBufHead[i]);
    }
    DBG_PRINTF("\n");
    
    /* 检查常见图片文件的魔数标识 */
    /* JPEG */
    if (fileSize >= 2 && pucBufHead[0] == 0xFF && pucBufHead[1] == 0xD8) {
        DBG_PRINTF("DEBUG: File identified as JPEG by magic number\n");
        return 0;
    }
    
    /* PNG */
    if (fileSize >= 8 && pucBufHead[0] == 0x89 && pucBufHead[1] == 'P' && 
        pucBufHead[2] == 'N' && pucBufHead[3] == 'G' &&
        pucBufHead[4] == 0x0D && pucBufHead[5] == 0x0A &&
        pucBufHead[6] == 0x1A && pucBufHead[7] == 0x0A) {
        DBG_PRINTF("DEBUG: File identified as PNG by magic number\n");
        return 0;
    }
    
    /* GIF */
    if (fileSize >= 6 && (
        (pucBufHead[0] == 'G' && pucBufHead[1] == 'I' && pucBufHead[2] == 'F' && 
         pucBufHead[3] == '8' && (pucBufHead[4] == '7' || pucBufHead[4] == '9') && pucBufHead[5] == 'a')
        )) {
        DBG_PRINTF("DEBUG: File identified as GIF by magic number\n");
        return 0;
    }
    
    /* BMP */
    if (fileSize >= 2 && pucBufHead[0] == 'B' && pucBufHead[1] == 'M') {
        DBG_PRINTF("DEBUG: File identified as BMP by magic number\n");
        return 0;
    }
    
    /* 首先检查文件扩展名 - 不区分大小写 */
    ext = strrchr(ptFileMap->strFileName, '.');
    if (ext) {
        ext++; /* 跳过点号 */
        DBG_PRINTF("DEBUG: File extension: %s\n", ext);
        
        /* 不区分大小写比较 */
        char lcExt[10] = {0};
        strncpy(lcExt, ext, 9);
        for (i = 0; lcExt[i]; i++) {
            if (lcExt[i] >= 'A' && lcExt[i] <= 'Z')
                lcExt[i] = lcExt[i] - 'A' + 'a';
        }
        
        /* 图像文件扩展名 - 排除这些 */
        if (strcmp(lcExt, "jpg") == 0 || 
            strcmp(lcExt, "jpeg") == 0 || 
            strcmp(lcExt, "png") == 0 || 
            strcmp(lcExt, "gif") == 0 || 
            strcmp(lcExt, "bmp") == 0 ||
            strcmp(lcExt, "webp") == 0 ||
            strcmp(lcExt, "tiff") == 0 ||
            strcmp(lcExt, "tif") == 0 ||
            strcmp(lcExt, "ico") == 0)
        {
            DBG_PRINTF("DEBUG: File extension indicates image file: %s\n", lcExt);
            return 0;
        }
        
        /* 全面支持的文本文件格式 */
        if (strcmp(lcExt, "txt") == 0 || 
            strcmp(lcExt, "md") == 0 || 
            strcmp(lcExt, "log") == 0 || 
            strcmp(lcExt, "ini") == 0 || 
            strcmp(lcExt, "xml") == 0 || 
            strcmp(lcExt, "json") == 0 || 
            strcmp(lcExt, "c") == 0 || 
            strcmp(lcExt, "h") == 0 || 
            strcmp(lcExt, "cpp") == 0 || 
            strcmp(lcExt, "py") == 0 ||
            strcmp(lcExt, "java") == 0 || 
            strcmp(lcExt, "html") == 0 || 
            strcmp(lcExt, "css") == 0 || 
            strcmp(lcExt, "js") == 0 || 
            strcmp(lcExt, "sh") == 0 || 
            strcmp(lcExt, "conf") == 0 || 
            strcmp(lcExt, "properties") == 0 || 
            strcmp(lcExt, "csv") == 0)
        {
            DBG_PRINTF("DEBUG: File extension indicates text file: %s\n", lcExt);
            return 1;  /* 文件扩展名表明这是文本文件 */
        }
    }
    
    /* 检查UTF-8 BOM */
    if (fileSize >= 3 && 
        pucBufHead[0] == 0xEF &&
        pucBufHead[1] == 0xBB && pucBufHead[2] == 0xBF)
    {
        DBG_PRINTF("DEBUG: UTF-8 BOM detected, confirming as text file\n");
        return 1;  /* UTF-8 BOM标识 */
    }
    
    /* 检查内容 - 只检查前16KB或文件大小(取较小值) */
    int checkSize = (fileSize < 16384) ? fileSize : 16384;
    DBG_PRINTF("DEBUG: Analyzing first %d bytes of file content\n", checkSize);
    
    /* 统计字符类型 */
    for (i = 0; i < checkSize; i++)
    {
        unsigned char c = pucBufHead[i]; 
        
        /* 统计NULL字节 */
        if (c == 0) {
            nullCount++;
            binCount += 1;  /* 降低NULL字节的二进制权重 */
            continue;
        }
        
        /* ASCII可打印字符和常见控制字符 */
        if ((c >= 32 && c <= 126) || c == '\n' || c == '\r' || c == '\t')
        {
            textCount++;
        }
        /* 国际字符(可能是UTF-8或其他编码) */
        else if (c >= 128)
        {
            textCount++;
        }
        /* 其他控制字符，可能是二进制数据 */
        else
        {
            binCount++;
        }
    }
    
    DBG_PRINTF("DEBUG: Character counts: ascii/intl text=%d, control=%d, null=%d, binary=%d\n", 
               textCount, binCount, nullCount);
    
    /* 如果二进制字符过多，认为不是文本文件，但放宽标准 */
    if (binCount > checkSize / 3) {
        DBG_PRINTF("DEBUG: Too many binary characters (%d/%d), rejecting as text\n", 
                   binCount, checkSize);
        return 0;
    }
    
    /* 文本字符应占主导地位 */
    if (textCount > checkSize * 0.5) {
        DBG_PRINTF("DEBUG: Text characters are dominant (%d/%d), accepting as text\n", 
                   textCount, checkSize);
        return 1;
    }
    
    /* 小文件特殊处理 - 即使有一些二进制特征也接受 */
    if (fileSize < 2048 && binCount < 50) {
        DBG_PRINTF("DEBUG: Small file with few binary chars, accepting as text\n");
        return 1;
    }
    
    /* 所有检查都未通过，默认不是文本文件 */
    DBG_PRINTF("DEBUG: File does not appear to be text\n");
    return 0;
}

/**********************************************************************
 * 函数名称： DetectTextEncoding
 * 功能描述： 检测文本编码类型
 * 输入参数： pucText - 文本内容
 *            iLength - 文本长度
 * 输出参数： 无
 * 返 回 值： 0 - UTF-8, 1 - GBK, 2 - 其他编码
 ***********************************************************************/
static int DetectTextEncoding(unsigned char *pucText, int iLength)
{
    int i;
    int iUtf8Count = 0;
    int iGBKCount = 0;
    
    if (!pucText || iLength <= 0)
        return 2;
    
    /* 检查是否有UTF-8 BOM */
    if (iLength >= 3 && pucText[0] == 0xEF && pucText[1] == 0xBB && pucText[2] == 0xBF)
        return 0;
    
    /* 扫描检测UTF-8和GBK特征 */
    for (i = 0; i < iLength; i++)
    {
        /* 检查UTF-8序列 */
        if ((pucText[i] & 0xE0) == 0xC0) /* 2字节UTF-8 */
        {
            if (i + 1 < iLength && (pucText[i+1] & 0xC0) == 0x80)
            {
                iUtf8Count++;
                i++;
            }
        }
        else if ((pucText[i] & 0xF0) == 0xE0) /* 3字节UTF-8 */
        {
            if (i + 2 < iLength && (pucText[i+1] & 0xC0) == 0x80 && (pucText[i+2] & 0xC0) == 0x80)
            {
                iUtf8Count++;
                i += 2;
            }
        }
        else if ((pucText[i] & 0xF8) == 0xF0) /* 4字节UTF-8 */
        {
            if (i + 3 < iLength && (pucText[i+1] & 0xC0) == 0x80 && 
                (pucText[i+2] & 0xC0) == 0x80 && (pucText[i+3] & 0xC0) == 0x80)
            {
                iUtf8Count++;
                i += 3;
            }
        }
        /* 检查GBK特征 */
        else if (pucText[i] >= 0x81 && pucText[i] <= 0xFE)
        {
            if (i + 1 < iLength && pucText[i+1] >= 0x40 && pucText[i+1] <= 0xFE)
            {
                iGBKCount++;
                i++;
            }
        }
    }
    
    /* 根据特征判断编码 */
    if (iUtf8Count > iGBKCount)
        return 0;
    else if (iGBKCount > 0)
        return 1;
    else
        return 2;
}

/**********************************************************************
 * 函数名称： ConvertTextEncoding
 * 功能描述： 转换文本编码
 * 输入参数： pucInText - 输入文本
 *            iInLength - 输入长度
 *            iEncoding - 输入编码 (0-UTF8, 1-GBK)
 * 输出参数： pucOutText - 输出文本(UTF-8)
 * 返 回 值： 转换后的文本长度，-1表示失败
 ***********************************************************************/
static int ConvertTextEncoding(unsigned char *pucInText, int iInLength, int iEncoding, unsigned char *pucOutText, int iOutBufSize)
{
    int i, j = 0;

    if (!pucInText || !pucOutText || iInLength <= 0)
        return -1;
    
    /* 如果已经是UTF-8，直接复制 */
    if (iEncoding == 0)
    {
        /* 跳过UTF-8的BOM */
        int iOffset = 0;
        if (iInLength >= 3 && pucInText[0] == 0xEF && pucInText[1] == 0xBB && pucInText[2] == 0xBF)
            iOffset = 3;
        
        /* 确保不会缓冲区溢出 */
        int iCopyLen = (iInLength - iOffset < iOutBufSize - 1) ? (iInLength - iOffset) : (iOutBufSize - 1);
        memcpy(pucOutText, pucInText + iOffset, iCopyLen);
        pucOutText[iCopyLen] = '\0';
        return iCopyLen;
    }
    
    /* GBK到UTF-8的简单转换 - 对于不能转换的字符使用问号代替 */
    for (i = 0; i < iInLength && j < iOutBufSize - 3; i++)
    {
        /* ASCII直接复制 */
        if (pucInText[i] < 0x80)
        {
            pucOutText[j++] = pucInText[i];
        }
        /* GBK双字节转UTF-8 - 这是一个简化版，不处理所有GBK字符 */
        else if (i + 1 < iInLength && pucInText[i] >= 0x81 && pucInText[i] <= 0xFE &&
                 pucInText[i+1] >= 0x40 && pucInText[i+1] <= 0xFE)
        {
            /* 对于复杂的GBK到UTF-8的转换，这里使用简单策略 */
            /* 产生一个3字节的UTF-8序列表示问号或空格 */
            pucOutText[j++] = ' ';
            i++; /* 跳过GBK的第二个字节 */
        }
        else
        {
            /* 不能识别的字符，使用问号 */
            pucOutText[j++] = '?';
        }
    }
    
    pucOutText[j] = '\0';
    return j;
}

/**********************************************************************
 * 函数名称： GetTextFromFile
 * 功能描述： 解析文本文件，准备显示内容
 * 输入参数： ptFileMap    - 文件映射结构体指针
 * 输出参数： ptTextContent - 存储解析后的文本内容
 * 返 回 值： 0 - 成功，其他 - 失败
 ***********************************************************************/
int GetTextFromFile(PT_FileMap ptFileMap, PT_TextContent ptTextContent)
{
    int iDataOffset = 0;
    unsigned char *pucFileStart;
    int iEncoding;
    
    /* 安全检查 */
    if (!ptFileMap || !ptFileMap->pucFileMapMem || !ptTextContent)
    {
        DBG_PRINTF("ERROR: Invalid parameters for GetTextFromFile\n");
        return -1;
    }
    
    /* 清除旧内容 */
    if (ptTextContent->pText)
    {
        free(ptTextContent->pText);
        ptTextContent->pText = NULL;
    }
    
    /* 初始化整个结构体 */
    memset(ptTextContent, 0, sizeof(T_TextContent));
    
    DBG_PRINTF("DEBUG: Processing file: %s, size: %d bytes\n", 
               ptFileMap->strFileName, ptFileMap->iFileSize);
    
    /* 检查文件大小 */
    if (ptFileMap->iFileSize <= 0)
    {
        DBG_PRINTF("ERROR: Invalid file size: %d\n", ptFileMap->iFileSize);
        return -1;
    }
    
    pucFileStart = ptFileMap->pucFileMapMem;
    
    /* 检测文本编码 */
    iEncoding = DetectTextEncoding(pucFileStart, ptFileMap->iFileSize);
    DBG_PRINTF("DEBUG: Detected text encoding: %d (0=UTF8, 1=GBK, 2=other)\n", iEncoding);
    
    /* 处理UTF-8 BOM */
    if (iEncoding == 0 && ptFileMap->iFileSize >= 3 && 
        pucFileStart[0] == 0xEF && pucFileStart[1] == 0xBB && pucFileStart[2] == 0xBF)
    {
        iDataOffset = 3;
        DBG_PRINTF("DEBUG: UTF-8 BOM detected, offset set to 3\n");
    }
    
    /* 限制文本大小 */
    int iTextLen = ptFileMap->iFileSize - iDataOffset;
    int iMaxTextSize = 128* 1024 * 1024; /* 限制为128KB  */
    
    if (iTextLen <= 0)
    {
        DBG_PRINTF("ERROR: Invalid text length after BOM offset: %d\n", iTextLen);
        return -1;
    }
    
    if (iTextLen > iMaxTextSize)
    {
        DBG_PRINTF("WARNING: File too large (%d bytes), limiting to %d bytes\n", 
                  iTextLen, iMaxTextSize);
        iTextLen = iMaxTextSize;
    }
    
    /* 分配内存，额外添加安全空间 */
    ptTextContent->iTextLen = iTextLen;
    ptTextContent->pText = malloc(iTextLen + 32); /* 添加32字节安全缓冲区 */
    
    if (NULL == ptTextContent->pText)
    {
        DBG_PRINTF("ERROR: malloc error for text content, requested size: %d bytes\n", 
                   iTextLen + 32);
        ptTextContent->iTextLen = 0;
        return -1;
    }
    
    /* 初始化整个内存区域为0 */
    memset(ptTextContent->pText, 0, iTextLen + 32);
    
    DBG_PRINTF("DEBUG: Memory allocated for text content: %d bytes\n", iTextLen + 32);
    
    /* 复制文本内容 */
    memcpy(ptTextContent->pText, pucFileStart + iDataOffset, iTextLen);
    
    /* 确保字符串正确结束 */
    ptTextContent->pText[iTextLen] = '\0'; 
    
    /* 去除不可显示字符 */
    int i;
    for (i = 0; i < iTextLen; i++)
    {
        /* 过滤掉除了可打印字符、换行、回车和Tab以外的控制字符 */
        if ((ptTextContent->pText[i] < 32 && 
            ptTextContent->pText[i] != '\n' && 
            ptTextContent->pText[i] != '\r' && 
            ptTextContent->pText[i] != '\t') || 
            ptTextContent->pText[i] == 0x7F)
        {
            ptTextContent->pText[i] = ' ';
        }
    }
    
    /* 初始化显示区域 */
    ptTextContent->iOffsetCurDispStart = 0;
    ptTextContent->iOffsetCurDispEnd = 0;
    
    /* 计算初始显示区域 - 从第一页开始 */
    if (!TextPageDown(ptTextContent)) {
        DBG_PRINTF("WARNING: Failed to calculate first page\n");
        
        /* 强制设置一个合理的显示区域 */
        ptTextContent->iOffsetCurDispStart = 0;
        ptTextContent->iOffsetCurDispEnd = (iTextLen > 500) ? 500 : iTextLen;
    }
    
    return 0;
}

/**********************************************************************
 * 函数名称： OpenTextFile
 * 功能描述： 打开并显示文本文件
 * 输入参数： ptFileMap    - 文件映射结构体指针
 * 输出参数： ptTextContent - 存储文本内容
 *            ptPixelDatas  - 显示缓冲区
 * 返 回 值： 0 - 成功，-1 - 失败
 ***********************************************************************/
int OpenTextFile(PT_FileMap ptFileMap, PT_TextContent ptTextContent, PT_PixelDatas ptPixelDatas)
{
    int iRet;

    if (!ptFileMap || !ptTextContent || !ptPixelDatas)
    {
        DBG_PRINTF("ERROR: Invalid parameters for OpenTextFile\n");
        return -1;
    }
    
    /* 详细的文件信息输出 */
    DBG_PRINTF("DEBUG: === Starting text file open process ===\n");
    DBG_PRINTF("DEBUG: File: %s, size: %d bytes\n", 
               ptFileMap->strFileName, ptFileMap->iFileSize);
    DBG_PRINTF("DEBUG: PixelDatas: %dx%d, %d bpp\n", 
               ptPixelDatas->iWidth, ptPixelDatas->iHeight, ptPixelDatas->iBpp);
    
    /* 1. 检查是否为文本文件 */
    DBG_PRINTF("DEBUG: Step 1 - Checking if file is text\n");
    if (!IsTxtFile(ptFileMap))
    {
        DBG_PRINTF("WARNING: Not identified as a text file: %s\n", ptFileMap->strFileName);
        
        /* 额外检查 - 如果文件小于1MB，尝试强制打开 */
        if (ptFileMap->iFileSize < 1024*1024)
        {
            DBG_PRINTF("DEBUG: File is small, force opening as text\n");
        }
        else
        {
            DBG_PRINTF("ERROR: File too large and not detected as text, abort opening\n");
            return -1;
        }
    }
    
    /* 2. 从文件获取文本内容 */
    DBG_PRINTF("DEBUG: Step 2 - Extracting text content\n");
    iRet = GetTextFromFile(ptFileMap, ptTextContent);
    if (iRet != 0)
    {
        DBG_PRINTF("ERROR: GetTextFromFile failed with code %d\n", iRet);
        return -1;
    }
    
    /* 3. 显示文本内容 */
    DBG_PRINTF("DEBUG: Step 3 - Rendering text to PixelDatas\n");
    iRet = ShowTextInPixelDatas(ptTextContent, ptPixelDatas);
    if (iRet != 0)
    {
        DBG_PRINTF("ERROR: ShowTextInPixelDatas failed with code %d\n", iRet);
        FreeTextContent(ptTextContent);
        return -1;
    }
    
    /* 4. 更新显示区域 - 刷新显示 */
    if (ptPixelDatas->iWidth && ptPixelDatas->iHeight)
    {
        DBG_PRINTF("DEBUG: Step 4 - Flushing text to display device\n");
        iRet = FlushPixelDatasToDev(ptPixelDatas);
        if (iRet != 0) {
            DBG_PRINTF("WARNING: FlushPixelDatasToDev returned %d, display may be incorrect\n", iRet);
        }
    }
    else {
        DBG_PRINTF("WARNING: Invalid PixelDatas dimensions, skipping flush to device\n");
    }
    
    DBG_PRINTF("DEBUG: === Text file opened successfully ===\n");
    return 0;
}


/**********************************************************************
 * 函数名称： ClearPixelDatas
 * 功能描述： 安全地清除PixelDatas中的所有数据
 * 输入参数： ptPixelDatas - 像素数据结构
 *            dwColor     - 用于清屏的颜色值
 * 输出参数： 无
 * 返 回 值： 0 - 成功，其他 - 失败
 ***********************************************************************/
static int ClearPixelDatas(PT_PixelDatas ptPixelDatas, unsigned int dwColor)
{
    int x, y;
    unsigned char *pucDst;
    int iBpp;
    
    if (!ptPixelDatas || !ptPixelDatas->aucPixelDatas)
    {
        return -1;
    }
    
    iBpp = ptPixelDatas->iBpp;
    
    /* 防止除零错误 */
    if (iBpp <= 0)
    {
        return -1;
    }
    
    for (y = 0; y < ptPixelDatas->iHeight; y++)
    {
        pucDst = ptPixelDatas->aucPixelDatas + y * ptPixelDatas->iLineBytes;
        for (x = 0; x < ptPixelDatas->iWidth; x++)
        {
            if (iBpp == 8)
            {
                *pucDst = (unsigned char)dwColor;
                pucDst++;
            }
            else if (iBpp == 16)
            {
                *(unsigned short *)pucDst = (unsigned short)dwColor;
                pucDst += 2;
            }
            else if (iBpp == 24)
            {
                *pucDst     = dwColor & 0xff;
                *(pucDst+1) = (dwColor >> 8) & 0xff;
                *(pucDst+2) = (dwColor >> 16) & 0xff;
                pucDst += 3;
            }
            else if (iBpp == 32)
            {
                *(unsigned int *)pucDst = dwColor;
                pucDst += 4;
            }
        }
    }
    
    return 0;
}

/**********************************************************************
 * 函数名称： DrawTextInPixelDatas
 * 功能描述： 备用的文本渲染函数，用简单字符渲染代替复杂字体渲染
 * 输入参数： iX, iY     - 文本起始坐标
 *            pucText    - 文本内容
 *            dwColor    - 文本颜色
 * 输出参数： ptPixelDatas - 输出的像素数据
 * 返 回 值： 0 - 成功，其他 - 失败
 ***********************************************************************/
static int DrawTextInPixelDatas(int iX, int iY, unsigned char *pucText, unsigned int dwColor, PT_PixelDatas ptPixelDatas)
{
    int i;
    int iLen;
    int iError = 0;
    unsigned char ucStrTmp[2];
    
    if (!pucText || !ptPixelDatas)
    {
        return -1;
    }
    
    iLen = strlen((char *)pucText);
    if (iLen == 0)
    {
        return 0;
    }
    
    /* 设置字体大小 */
    SetFontSize(16);
    
    /* 使用逐字符显示的方法，避免一次处理过长的字符串 */
    ucStrTmp[1] = '\0';
    
    for (i = 0; i < iLen && i < 500; i++)  /* 限制处理字符数量 */
    {
        /* 跳过控制字符 */
        if (pucText[i] < 32 && pucText[i] != '\n' && pucText[i] != '\t')
        {
            continue;
        }
        
        /* 处理换行符 */
        if (pucText[i] == '\n')
        {
            iY += 20;  /* 行高固定为20像素 */
            iX = 10;   /* 回到行首，留出10像素边距 */
            continue;
        }
        
        /* 处理制表符 */
        if (pucText[i] == '\t')
        {
            iX += 40;  /* 制表符宽度为40像素 */
            continue;
        }
        
        /* 显示单个字符 */
        ucStrTmp[0] = pucText[i];
        
        /* 直接使用安全版本的MergerStringToPixelDatas函数 */
        iError = MergerStringToPixelDatas(iX, iY, ucStrTmp, dwColor, ptPixelDatas);
        if (iError)
        {
            /* 如果失败，尝试使用空格替代 */
            ucStrTmp[0] = ' ';
            iError = MergerStringToPixelDatas(iX, iY, ucStrTmp, dwColor, ptPixelDatas);
        }
        
        /* 字符宽度固定为10像素 */
        iX += 10;
        
        /* 如果到达行尾，换行 */
        if (iX > ptPixelDatas->iWidth - 20)
        {
            iY += 20;
            iX = 10;
        }
    }
    
    return iError;
}

/**********************************************************************
 * 函数名称： DrawSafeTextInPixelDatas
 * 功能描述： 安全的文本绘制函数 - 逐字符处理
 * 输入参数： iX, iY - 显示坐标
 *            pcText - 文本内容
 *            dwColor - 文本颜色
 *            ptPixelDatas - 显存
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他 - 失败
 ***********************************************************************/
static int DrawSafeTextInPixelDatas(int iX, int iY, const char *pcText, unsigned int dwColor, PT_PixelDatas ptPixelDatas)
{
    unsigned char ucBuf[2];
    int i;
    int iLen;
    
    if (!pcText || !ptPixelDatas)
        return -1;
    
    iLen = strlen(pcText);
    if (iLen == 0)
        return 0;
    
    ucBuf[1] = '\0';
    
    /* 逐字符绘制，避免一次处理整个字符串 */
    for (i = 0; i < iLen; i++)
    {
        ucBuf[0] = pcText[i];
        
        /* 仅处理可打印ASCII字符 */
        if (ucBuf[0] >= 32 && ucBuf[0] < 127)
        {
            MergerStringToPixelDatas(iX + i*10, iY, ucBuf, dwColor, ptPixelDatas);
        }
    }
    
    return 0;
}

/**********************************************************************
 * 函数名称： ShowTextInPixelDatas
 * 功能描述： 在指定区域显示文本内容
 * 输入参数： ptTextContent - 文本内容
 * 输出参数： ptPixelDatas  - 显示缓冲区
 * 返 回 值： 0 - 成功，其他 - 失败
 ***********************************************************************/
int ShowTextInPixelDatas(PT_TextContent ptTextContent, PT_PixelDatas ptPixelDatas)
{
    /* 检查参数 */
    if (!ptTextContent || !ptTextContent->pText || !ptPixelDatas || !ptPixelDatas->aucPixelDatas)
    {
        DBG_PRINTF("ERROR: Invalid parameters for ShowTextInPixelDatas\n");
        return -1;
    }
    
    /* 填充背景色 */
    int y, x;
    unsigned char *pucDst;
    unsigned int dwBackgroundColor = 0xFFFFFF; /* 白色背景 */
    
    /* 按行填充背景色 */
    for (y = 0; y < ptPixelDatas->iHeight; y++)
    {
        pucDst = ptPixelDatas->aucPixelDatas + y * ptPixelDatas->iLineBytes;
        
        for (x = 0; x < ptPixelDatas->iWidth; x++)
        {
            /* 根据不同的bpp填充不同的数据 */
            if (ptPixelDatas->iBpp == 8)
            {
                *pucDst = (unsigned char)dwBackgroundColor;
                pucDst++;
            }
            else if (ptPixelDatas->iBpp == 16)
            {
                /* RGB565 */
                *(unsigned short *)pucDst = (unsigned short)
                    (((dwBackgroundColor >> 16) & 0xFF) >> 3) << 11 | 
                    (((dwBackgroundColor >> 8) & 0xFF) >> 2) << 5 | 
                    ((dwBackgroundColor & 0xFF) >> 3);
                pucDst += 2;
            }
            else if (ptPixelDatas->iBpp == 24)
            {
                *pucDst++ = dwBackgroundColor & 0xFF;
                *pucDst++ = (dwBackgroundColor >> 8) & 0xFF;
                *pucDst++ = (dwBackgroundColor >> 16) & 0xFF;
            }
            else if (ptPixelDatas->iBpp == 32)
            {
                *(unsigned int *)pucDst = dwBackgroundColor;
                pucDst += 4;
            }
        }
    }
    
    /* 确定显示区域 */
    int iStart = ptTextContent->iOffsetCurDispStart;
    int iEnd = ptTextContent->iOffsetCurDispEnd;
    
    /* 边界检查 */
    if (iStart < 0) iStart = 0;
    if (iStart >= ptTextContent->iTextLen) iStart = 0;
    if (iEnd <= iStart) iEnd = ptTextContent->iTextLen;
    if (iEnd > ptTextContent->iTextLen) iEnd = ptTextContent->iTextLen;
    
    DBG_PRINTF("ShowTextInPixelDatas: range %d to %d (total length: %d)\n", 
               iStart, iEnd, ptTextContent->iTextLen);
    
    /* 在屏幕顶部显示文件信息 */
    char strInfo[128];
    snprintf(strInfo, sizeof(strInfo), "Text Viewer - Size: %d bytes", ptTextContent->iTextLen);
    
    /* 显示标题 - 使用最简单的方式绘制ASCII文本 */
    int iTitleX = 10;
    int iTitleY = 10;
    int i, iLen = strlen(strInfo);
    unsigned char *pucBuf;
    
    /* 设置小号字体大小 */
    SetFontSize(12);
    
    /* 绘制标题 */
    for (i = 0; i < iLen; i++)
    {
        if (strInfo[i] >= 32 && strInfo[i] < 127)
        {
            pucBuf = malloc(2);
            if (pucBuf)
            {
                pucBuf[0] = strInfo[i];
                pucBuf[1] = '\0';
                
                /* 将字符水平排列 */
                MergerStringToPixelDatas(iTitleX + i*8, iTitleY, pucBuf, 0x0000FF, ptPixelDatas);
                
                free(pucBuf);
            }
        }
    }
    
    /* 设置较大字体大小 */
    SetFontSize(16);
    
    /* 尝试显示文本内容 - 使用最简单的方式 */
    int iTextX = 10;
    int iTextY = 40;
    int iCharCount = 0;
    int iLineChars = (ptPixelDatas->iWidth - 20) / 8; /* 计算每行可显示的字符数 */
    
    /* 简单地逐行逐字绘制 */
    for (i = iStart; i < iEnd && i < ptTextContent->iTextLen; i++)
    {
        unsigned char c = ptTextContent->pText[i];
        
        /* 处理换行 */
        if (c == '\n')
        {
            iTextY += 20;
            iTextX = 10;
            iCharCount = 0;
            continue;
        }
        
        /* 处理回车 */
        if (c == '\r')
            continue;
            
        /* 自动换行 */
        if (iCharCount >= iLineChars)
        {
            iTextY += 20;
            iTextX = 10;
            iCharCount = 0;
        }
        
        /* 如果超出底部，停止显示 */
        if (iTextY >= ptPixelDatas->iHeight - 30)
            break;
            
        /* 只显示ASCII字符 */
        if (c >= 32 && c < 127)
        {
            pucBuf = malloc(2);
            if (pucBuf)
            {
                pucBuf[0] = c;
                pucBuf[1] = '\0';
                
                MergerStringToPixelDatas(iTextX, iTextY, pucBuf, 0x000000, ptPixelDatas);
                
                free(pucBuf);
            }
            iTextX += 8;
            iCharCount++;
        }
        else if (c >= 128) /* 非ASCII字符 */
        {
            /* 用问号替代 */
            pucBuf = malloc(2);
            if (pucBuf)
            {
                pucBuf[0] = '?';
                pucBuf[1] = '\0';
                
                MergerStringToPixelDatas(iTextX, iTextY, pucBuf, 0x000000, ptPixelDatas);
                
                free(pucBuf);
            }
            iTextX += 8;
            iCharCount++;
            
            /* 跳过多字节字符的后续字节 */
            if ((c & 0xE0) == 0xC0) /* 2字节UTF-8 */
                i++;
            else if ((c & 0xF0) == 0xE0) /* 3字节UTF-8 */
                i += 2;
            else if ((c & 0xF8) == 0xF0) /* 4字节UTF-8 */
                i += 3;
        }
    }
    
    /* 在底部显示页码信息 */
    snprintf(strInfo, sizeof(strInfo), "Page %d/%d", 
             (iStart / 1000) + 1, 
             (ptTextContent->iTextLen + 999) / 1000);
             
    SetFontSize(12);
    iLen = strlen(strInfo);
    
    for (i = 0; i < iLen; i++)
    {
        if (strInfo[i] >= 32 && strInfo[i] < 127)
        {
            pucBuf = malloc(2);
            if (pucBuf)
            {
                pucBuf[0] = strInfo[i];
                pucBuf[1] = '\0';
                
                MergerStringToPixelDatas(ptPixelDatas->iWidth - 100 + i*8, ptPixelDatas->iHeight - 20, pucBuf, 0x0000FF, ptPixelDatas);
                
                free(pucBuf);
            }
        }
    }
    
    return 0;
}

/**********************************************************************
 * 函数名称： FreePageList
 * 功能描述： 释放页面链表
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void FreePageList(void)
{
    PT_PageDesc ptPage;
    PT_PageDesc ptTmp;
    
    ptPage = g_ptPages;
    while (ptPage)
    {
        ptTmp = ptPage;
        ptPage = ptPage->ptNextPage;
        free(ptTmp);
    }
    
    g_ptPages = NULL;
    g_ptCurPage = NULL;
}


/**********************************************************************
 * 函数名称： FreeTextContent
 * 功能描述： 释放文本内容所占内存
 * 输入参数： ptTextContent - 文本内容
 * 输出参数： 无
 * 返 回 值： 0 - 成功
 ***********************************************************************/
int FreeTextContent(PT_TextContent ptTextContent)
{
    if (ptTextContent)
    {
        if (ptTextContent->pText)
        {
            free(ptTextContent->pText);
            ptTextContent->pText = NULL;
        }
        ptTextContent->iOffsetCurDispStart = 0;
        ptTextContent->iOffsetCurDispEnd = 0;
        ptTextContent->iTextLen = 0;
    }
    
    /* 释放页面链表 */
    FreePageList();
    
    return 0;
}

/**********************************************************************
 * 函数名称： TextPageDown
 * 功能描述： 文本向下翻页
 * 输入参数： ptTextContent - 文本内容
 * 输出参数： 无
 * 返 回 值： 1 - 成功翻页, 0 - 已到末尾
 ***********************************************************************/
int TextPageDown(PT_TextContent ptTextContent)
{
    int iStart;
    int iEnd;
    int i;
    int iLineCount = 0;
    int iMaxLines = g_tTextReaderCfg.iLinesPerScreen;  /* 使用计算值替代固定值40 */
    int iMaxCharsPerLine = g_tTextReaderCfg.iCharsPerLine;  /* 使用计算值替代固定值100 */
    PT_PageDesc ptPage;
    
    /* 安全检查 */
    if (!ptTextContent || !ptTextContent->pText || ptTextContent->iTextLen <= 0)
    {
        DBG_PRINTF("ERROR: Invalid TextContent in TextPageDown\n");
        return 0;
    }

    /* 检查是否有记录的下一页 */
    if (g_ptCurPage && g_ptCurPage->ptNextPage)
    {
        /* 直接使用已记录的下一页 */
        g_ptCurPage = g_ptCurPage->ptNextPage;
        ptTextContent->iOffsetCurDispStart = g_ptCurPage->iStartPos;
        ptTextContent->iOffsetCurDispEnd = g_ptCurPage->iEndPos;
        
        DBG_PRINTF("TextPageDown: Using cached page %d (%d to %d)\n", 
                  g_ptCurPage->iPage, g_ptCurPage->iStartPos, g_ptCurPage->iEndPos);
        return 1;
    }
    
    /* 如果已经是文档末尾，无法再向下翻页 */
    if (ptTextContent->iOffsetCurDispEnd >= ptTextContent->iTextLen)
    {
        DBG_PRINTF("DEBUG: Already at end of text, can't page down\n");
        return 0;
    }
    
    /* 设置当前页面的起始位置 */
    iStart = ptTextContent->iOffsetCurDispEnd;
    
    /* 确保不超出文本范围 */
    if (iStart >= ptTextContent->iTextLen)
    {
        DBG_PRINTF("ERROR: Start offset (%d) exceeds text length (%d)\n", 
                  iStart, ptTextContent->iTextLen);
        iStart = 0;  /* 回到文本开头 */
    }
    
    iEnd = iStart;
    DBG_PRINTF("TextPageDown: starting from offset %d\n", iStart);
    
    /* 计算显示范围 - 最多显示iMaxLines行 */
    int iCharsProcessed = 0;
    int iMaxChars = 100000;  /* 限制最多处理的字符数 */
    
    /* 安全边界检查 */
    if (iStart + iMaxChars > ptTextContent->iTextLen)
    {
        iMaxChars = ptTextContent->iTextLen - iStart;
    }
    
    /* 逐字符扫描，确保不会越界 */
    for (i = 0; i < iMaxChars && iEnd < ptTextContent->iTextLen - 1; i++) 
    {
        char c = ptTextContent->pText[iEnd];
        iCharsProcessed++;
        
        /* 遇到换行符计数增加 */
        if (c == '\n') 
        {
            iLineCount++;
            /* 如果已达到最大行数，则停止 */
            if (iLineCount >= iMaxLines) 
            {
                iEnd++;
                break;
            }
        }
           
        /* 行内字符计数 */
        if (c == '\n' || c == '\r') 
        {
            /* 重置当前行字符计数 */
            iCharsProcessed = 0;
        } 
        else if (iCharsProcessed >= iMaxCharsPerLine) 
        {
            /* 如果当前行字符过多，强制换行 */
            iLineCount++;
            iCharsProcessed = 0;
            if (iLineCount >= iMaxLines) 
            {
                break;
            }
        }
        
        iEnd++;
    }
    
    /* 确保不超出文本长度 */
    if (iEnd > ptTextContent->iTextLen)
    {
        DBG_PRINTF("WARNING: End offset %d exceeds text length %d, adjusting\n", 
                  iEnd, ptTextContent->iTextLen);
        iEnd = ptTextContent->iTextLen;
    }
    
    /* 确保页面间有最小的页面移动量 */
    if (iEnd <= iStart + 100 && iEnd < ptTextContent->iTextLen) {
        int iMinPageSize = 500;
        if (iStart + iMinPageSize < ptTextContent->iTextLen) {
            iEnd = iStart + iMinPageSize;
        } else {
            iEnd = ptTextContent->iTextLen;
        }
        DBG_PRINTF("TextPageDown: Enforcing minimum page size, new end: %d\n", iEnd);
    }
    
    DBG_PRINTF("TextPageDown: calculated display range %d to %d (lines: %d)\n", 
               iStart, iEnd, iLineCount);
    
    /* 创建新的页面记录 */
    ptPage = malloc(sizeof(T_PageDesc));
    if (ptPage)
    {
        /* 设置页面数据 */
        if (g_ptCurPage)
            ptPage->iPage = g_ptCurPage->iPage + 1;
        else
            ptPage->iPage = 1;
            
        ptPage->iStartPos = iStart;
        ptPage->iEndPos = iEnd;
        ptPage->ptPrePage = NULL;
        ptPage->ptNextPage = NULL;
        
        /* 添加到链表 */
        if (g_ptCurPage)
        {
            g_ptCurPage->ptNextPage = ptPage;
            ptPage->ptPrePage = g_ptCurPage;
        }
        else
        {
            RecordPage(ptPage);
        }
        g_ptCurPage = ptPage;
        
        DBG_PRINTF("TextPageDown: created new page %d (%d to %d)\n", 
                  ptPage->iPage, ptPage->iStartPos, ptPage->iEndPos);
    }
    
    /* 更新显示区域 */
    ptTextContent->iOffsetCurDispStart = iStart;
    ptTextContent->iOffsetCurDispEnd = iEnd;
    
    return 1;
}

/**********************************************************************
 * 函数名称： TextPageUp
 * 功能描述： 文本向上翻页
 * 输入参数： ptTextContent - 文本内容
 * 输出参数： 无
 * 返 回 值： 1 - 成功翻页, 0 - 已到开头
 ***********************************************************************/
int TextPageUp(PT_TextContent ptTextContent)
{
    /* 安全检查 */
    if (!ptTextContent || !ptTextContent->pText || ptTextContent->iTextLen <= 0)
    {
        DBG_PRINTF("ERROR: Invalid TextContent in TextPageUp\n");
        return 0;
    }
    
    /* 如果已经是文档开头，无法再向上翻页 */
    if (ptTextContent->iOffsetCurDispStart == 0)
    {
        DBG_PRINTF("DEBUG: Already at start of text, can't page up\n");
        return 0;
    }
    
    /* 检查是否有上一页的缓存 */
    if (g_ptCurPage && g_ptCurPage->ptPrePage)
    {
        /* 使用上一页的缓存 */
        g_ptCurPage = g_ptCurPage->ptPrePage;
        ptTextContent->iOffsetCurDispStart = g_ptCurPage->iStartPos;
        ptTextContent->iOffsetCurDispEnd = g_ptCurPage->iEndPos;
        
        DBG_PRINTF("TextPageUp: Using cached previous page %d (%d to %d)\n", 
                  g_ptCurPage->iPage, g_ptCurPage->iStartPos, g_ptCurPage->iEndPos);
        return 1;
    }
    
    /* 没有缓存的上一页，我们需要基于当前位置向前计算 */
    DBG_PRINTF("TextPageUp: No cache, calculating previous page\n");
    
    /* 这种情况应该很少发生，因为我们会缓存所有页面
     * 但为防万一，还是实现一个基础版本
     */
    int iNewStart = ptTextContent->iOffsetCurDispStart / 2; /* 简单估算前一页的位置 */
    
    /* 确保不小于0 */
    if (iNewStart < 0) iNewStart = 0;
    
    /* 从估算位置向前找到行首 */
    while (iNewStart > 0 && ptTextContent->pText[iNewStart] != '\n')
    {
        iNewStart--;
    }
    
    /* 如果找到了换行符，从下一个字符开始 */
    if (iNewStart > 0 && ptTextContent->pText[iNewStart] == '\n')
    {
        iNewStart++;
    }
    
    /* 更新当前页面的起始位置 */
    ptTextContent->iOffsetCurDispStart = iNewStart;
    ptTextContent->iOffsetCurDispEnd = iNewStart;
    
    /* 调用下一页函数计算这一页的结束位置 */
    TextPageDown(ptTextContent);
    
    DBG_PRINTF("TextPageUp: Calculated new page from %d to %d\n", 
               ptTextContent->iOffsetCurDispStart, ptTextContent->iOffsetCurDispEnd);
    
    return 1;
}

/**********************************************************************
 * 函数名称： ConvertUnsupportedChars
 * 功能描述： 转换无法显示的字符为可显示字符
 * 输入参数： pucText - 文本字符串
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
__attribute__((unused))
static void ConvertUnsupportedChars(char *pucText)
{
    int i = 0;

    if (!pucText)
        return;
    
    /* 全面处理所有可能导致方框显示的字符 */
    while (pucText[i])
    {
        /* 除了可见ASCII字符和基本控制字符外，都替换为空格 */
        if ((pucText[i] < 32 && pucText[i] != '\n' && pucText[i] != '\r' && pucText[i] != '\t') || 
            (pucText[i] >= 127 && pucText[i] <= 159) ||  /* 处理扩展ASCII控制字符 */
            pucText[i] == 0x1A || pucText[i] == 0xFF || pucText[i] == 0xFE)
        {
            pucText[i] = ' ';
        }

        /* 专门处理制表符 */
        if (pucText[i] == '\t') {
            pucText[i] = ' ';
        }
        
        i++;
    }
}

/**********************************************************************
 * 函数名称： FlushPixelDatasToDev
 * 功能描述： 把PixelDatas中的数据刷到显示设备上去
 * 输入参数： ptPixelDatas - 包含显示数据的PixelDatas结构体
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 ***********************************************************************/
int FlushPixelDatasToDev(PT_PixelDatas ptPixelDatas)
{
    PT_DispOpr ptDispOpr;
    
    if (!ptPixelDatas || !ptPixelDatas->aucPixelDatas)
    {
        DBG_PRINTF("ERROR: Invalid PixelDatas pointer\n");
        return -1;
    }
    
    /* 获取默认显示设备 */
    ptDispOpr = GetDefaultDispDev();
    if (!ptDispOpr)
    {
        DBG_PRINTF("ERROR: No display device available\n");
        return -1;
    }
    
    DBG_PRINTF("DEBUG: Flushing %dx%d %d-bpp PixelDatas to display device\n", 
               ptPixelDatas->iWidth, ptPixelDatas->iHeight, ptPixelDatas->iBpp);
    
    /* 使用显示设备的合适接口 */
    if (ptDispOpr->ShowPage)
    {
        DBG_PRINTF("DEBUG: Using ShowPage method\n");
        /* 创建临时VideoMem结构用于显示 */
        T_VideoMem tVideoMem;
        
        /* 初始化VideoMem结构 */
        memset(&tVideoMem, 0, sizeof(T_VideoMem));
        memcpy(&tVideoMem.tPixelDatas, ptPixelDatas, sizeof(T_PixelDatas));
        
        /* 使用显示设备的ShowPage接口显示数据 */
        ptDispOpr->ShowPage(&tVideoMem);
        DBG_PRINTF("DEBUG: ShowPage called successfully\n");
    }
    else if (ptDispOpr->pucDispMem)
    {
        DBG_PRINTF("DEBUG: Using direct memory copy to display buffer\n");
        /* 如果有显存，直接拷贝到显存 */
        int iMemSize = ptPixelDatas->iHeight * ptPixelDatas->iLineBytes;
        memcpy(ptDispOpr->pucDispMem, ptPixelDatas->aucPixelDatas, iMemSize);
        DBG_PRINTF("DEBUG: Copied %d bytes directly to display memory\n", iMemSize);
    }
    else
    {
        /* 如果没有合适的显示接口，报错 */
        DBG_PRINTF("ERROR: Display device doesn't support any display method\n");
        return -1;
    }
    
    DBG_PRINTF("DEBUG: Flush to display device completed\n");
    return 0;
}

/**********************************************************************
 * 函数名称： TextReaderInit
 * 功能描述： 初始化文本阅读器
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 ***********************************************************************/
int TextReaderInit(void)
{
    PT_DispOpr ptDispOpr;
    
    /* 防止重复初始化 */
    if (g_tTextReaderCfg.iInited)
    {
        return 0;
    }
    
    /* 获取显示设备信息以计算默认参数 */
    ptDispOpr = GetDefaultDispDev();
    if (ptDispOpr && ptDispOpr->iXres > 0 && ptDispOpr->iYres > 0)
    {
        /* 根据屏幕分辨率计算默认的行数和字符数 */
        g_tTextReaderCfg.iLinesPerScreen = ptDispOpr->iYres / (g_tTextReaderCfg.iDefaultFontSize );
        g_tTextReaderCfg.iCharsPerLine = ptDispOpr->iXres / (g_tTextReaderCfg.iDefaultFontSize / 2);
        
        DBG_PRINTF("Text reader initialized: screen size %dx%d, lines per screen: %d, chars per line: %d\n",
                   ptDispOpr->iXres, ptDispOpr->iYres,
                   g_tTextReaderCfg.iLinesPerScreen, g_tTextReaderCfg.iCharsPerLine);
    }
    else
    {
        /* 如果无法获取显示设备信息，使用默认值 */
        DBG_PRINTF("Warning: Cannot get display info, using default text reader settings\n");
    }
    
    /* 标记为已初始化 */
    g_tTextReaderCfg.iInited = 1;
    
    return 0;
}
/**********************************************************************
 * 函数名称： MergerStringToVideoMem
 * 功能描述： 在VideoMem的指定位置显示字符串
 * 输入参数： iX, iY - 显示位置
 *            pucString - 字符串
 *            dwColor - 显示颜色
 * 输出参数： ptVideoMem - VideoMem
 * 返 回 值： 0 - 成功, -1 - 失败
 ***********************************************************************/
int MergerStringToVideoMem(int iX, int iY, unsigned char *pucString, unsigned int dwColor, PT_VideoMem ptVideoMem)
{
    unsigned char *pucTextTmp;
    int iLen;
    int iError;
    
    if (!pucString || !ptVideoMem)
    {
        return -1;
    }
    
    iLen = strlen((char *)pucString);
    if (iLen <= 0)
    {
        return -1;
    }
    
    /* 字符串尽量不超过20个字符 */
    if (iLen > 20)
    {
        iLen = 20;
    }
    
    /* 分配临时缓冲区存放截断后的字符串 */
    pucTextTmp = malloc(iLen + 1);
    if (!pucTextTmp)
    {
        return -1;
    }
    
    /* 拷贝并确保以NULL结尾 */
    strncpy((char *)pucTextTmp, (char *)pucString, iLen);
    pucTextTmp[iLen] = '\0';
    
    /* 尝试使用更安全的方法显示文本 */
    if (ptVideoMem->tPixelDatas.iBpp == 8 || 
        ptVideoMem->tPixelDatas.iBpp == 16 || 
        ptVideoMem->tPixelDatas.iBpp == 24 || 
        ptVideoMem->tPixelDatas.iBpp == 32)
    {
        /* 使用更安全的方法 - 避免MergerStringToCenterOfRectangleInVideoMem可能的不稳定性 */
        SetFontSize(16);
        for (int i = 0; i < iLen && pucTextTmp[i]; i++)
        {
            unsigned char c = pucTextTmp[i];
            if (c >= 32 && c < 127)
            {
                unsigned char singleChar[2] = {c, '\0'};
                /* 使用单字符调用，防止崩溃 */
                MergerStringToPixelDatas(iX + i*10, iY, singleChar, dwColor, &ptVideoMem->tPixelDatas);
            }
        }
        iError = 0;
    }
    else
    {
        /* 调用原渲染函数 */
        iError = MergerStringToCenterOfRectangleInVideoMem(iX, iY, iX + 200, iY + 30, pucTextTmp, ptVideoMem);
    }
    
    free(pucTextTmp);
    
    return iError;
}


